﻿#include "guild_service_building_context.h"

#include "BuildingUpgradeArg_struct.h"
#include "BuildingUpgradeRes_struct.h"
#include "CrystalPrayArg_struct.h"
#include "CrystalPrayRes_struct.h"
#include "CrystalChargeArg_struct.h"
#include "CrystalChargeRes_struct.h"

#include "box/service_context.hh"
#include "error/make_error_code.h"
#include "fwd.h"

#include "logic/guild_building_logic.h"
#include "logic/guild_crystal_logic.h"

#include "guild/guild.h"

#include "token/service_token_mgr.hpp"

namespace guild_service {
bool GuildServiceBuildingContext::Start(kratos::service::ServiceContext *context) {
  if (!GuildServiceBuildingContext::Init(context)) {
    LOG_FAIL("公会建筑服务启动失败");
    return false;
  }

  return register_service(std::string(kGuildServicePrefix) + std::string(kGuildServiceBuildingName));
}

bool GuildServiceBuildingContext::Stop() {
  LOG_INFO("公会建筑服务关闭");

  if (!unregister_service(std::string(kGuildServicePrefix) +
                          std::string(kGuildServiceBuildingName))) {
    LOG_FAIL("公会建筑服务关闭失败");
    return false;
  }

  return GuildServiceBuildingContext::Uninit();
}

bool GuildServiceBuildingContext::Init(kratos::service::ServiceContext *context) {
  if (!context) {
    return false;
  }

  if (!common::singleton_start<common::service_logger>(
          context, kGuildServiceBuildingName)) {
    return false;
  }

  LOG_INFO("公会建筑服务启动");

  if (!common::singleton_start<common::service_context>(context)) {
    LOG_FAIL("公会建筑服务启动失败");
    return false;
  }

  if (!common::singleton_start<common::service_redis_client>(context)) {
    LOG_FAIL("公会建筑服务启动失败");
    return false;
  }

  std::string redis_host(kRedisHost);
  int32_t redis_port = kRedisPort;
  std::string redis_user(kRedisUser);
  std::string redis_passwd(kRedisPasswd);
  
  {  // config.redis
    auto *config_ptr = ServiceContextSingleton()->get_config().get_config_ptr();
    if (!config_ptr) {
      LOG_FAIL("公会认证服务启动失败");
      return false;
    }
    if (config_ptr->has("redis")) {
      if (config_ptr->has("redis.host")) {
        redis_host = config_ptr->getString("redis.host");
      }
      if (config_ptr->has("redis.port")) {
        redis_port = config_ptr->getInt32("redis.port");
      }
      if (config_ptr->has("redis.user")) {
        redis_user = config_ptr->getString("redis.user");
      }
      if (config_ptr->has("redis.passwd")) {
        redis_passwd = config_ptr->getString("redis.passwd");
      }
    }
  }
  if (!redis_add_host(kGuildServiceBuildingName, redis_host, redis_port,
                      redis_user, redis_passwd)) {
    LOG_FAIL("公会建筑服务启动失败");
    return false;
  }

  if (!common::singleton_start<common::util>(context)) {
    LOG_FAIL("公会建筑服务启动失败");
    return false;
  }

  return true;
}

bool GuildServiceBuildingContext::Uninit() {
  return common::singleton_stop<common::service_redis_client>() &&
         common::singleton_stop<common::util>() &&
         common::singleton_stop<common::service_context>() &&
         common::singleton_stop<common::service_logger>();
}

void GuildServiceBuildingContext::Tick(time_t ms) {
  common::singleton_update<common::service_redis_client>(ms);
}

void GuildServiceBuildingContext::BuildingUpgrade(
    rpc::StubCallPtr call, const BuildingUpgradeArg &arg,
    std::shared_ptr<BuildingUpgradeRes> &res) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceBuildingName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }

  error_code ec(ErrorCode::ERR_SUCCESS);

  if (!GuildModuleBuildingLogic::BuildingUpgrade(role_uuid, arg.building_id, ec)) {
    LOG_WARN("公会建筑升级失败 角色唯一id:%llu 建筑id:%u 错误:%s",
             role_uuid, arg.building_id, ec.message().c_str());
    res->result = static_cast<ErrorCode>(ec.value());
    return;
  }

  res->result = static_cast<ErrorCode>(ec.value());
}
  
void GuildServiceBuildingContext::CrystalPray(rpc::StubCallPtr call, const CrystalPrayArg &arg,
                             std::shared_ptr<CrystalPrayRes> &res) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceBuildingName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }

  error_code ec(ErrorCode::ERR_SUCCESS);
  if (!GuildModuleCrystalLogic::CrystalPray(role_uuid, arg.id, ec)) {
    // res->result = ErrorCode::ERR_GUILD_MOD_
    return;
  }

  res->result = static_cast<ErrorCode>(ec.value());
}

void GuildServiceBuildingContext::CrystalCharge(rpc::StubCallPtr call, const CrystalChargeArg &arg,
                             std::shared_ptr<CrystalChargeRes> &res) {
  token_type token = detail::GetToken(call);
#ifdef DEBUG
  token = arg.token;
#endif

  if (token == kInvalidToken) {
    res->result = ErrorCode::ERR_INVALID_TOKEN;
    return;
  }

  role_uuid_type role_uuid =
      detail::GetRoleUuid(kGuildServiceBuildingName, token);
  if (role_uuid == kInvalidRoleUuid) {
    res->result = ErrorCode::ERR_INVALID_ROLE_UUID;
    return;
  }

  error_code ec(ErrorCode::ERR_SUCCESS);
  // TODO
  res->result = static_cast<ErrorCode>(ec.value());
}


};  // namespace guild_service